package com.company.cloud.club.modules.core.dto;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.Data;

import java.io.Serializable;
import java.util.Map;

/**
 * @param <T> Data
 * @author buff
 */
@Data
@JsonSerialize
@JsonInclude(value = JsonInclude.Include.NON_NULL)
public class Result<T> implements Serializable {

    /**
     * 成功码.
     */
    public static final int SUCCESS_CODE = 0;

    /**
     * 默认错误
     */
    public static final int DEFAULT_ERROR = 0xe0;
    /**
     * 验证错误
     */
    public static final int VALID_ERROR = 0xe1;
    /**
     * 未授权
     */
    public static final int NO_AUTH = 0xe2;
    /**
     * 错误的请求
     */
    public static final int BAD_REQ = 0xe3;
    /**
     * 未登录
     */
    public static final int NO_LOGIN = 0xe4;
    /**
     * 服务器错误
     */
    public static final int SERVER_ERROR = 0xe5;
    /**
     * 请求速率错误
     */
    public static final int RATE_LIMIT_ERROR = 0xe6;

    /**
     * 数据请求失败
     */
    public static final int DATA_FAIL_CODE = 500;

    /**
     * code
     */
    private int code;

    /**
     * 信息
     */
    @JsonInclude(JsonInclude.Include.NON_DEFAULT)
    private String msg;
    @JsonInclude(JsonInclude.Include.NON_DEFAULT)
    private Map<Object, Object> extra;
    /**
     * 结果数据
     */
    @JsonInclude(JsonInclude.Include.NON_NULL)
    private T data;
    @JsonInclude(JsonInclude.Include.NON_DEFAULT)
    private int page;
    @JsonInclude(JsonInclude.Include.NON_DEFAULT)
    private int limit;
    @JsonInclude(JsonInclude.Include.NON_DEFAULT)
    private int count;

    /**
     * Instantiates a new wrapper. default packageCode=0
     */
    public Result() {
        this(SUCCESS_CODE);
    }

    /**
     * Instantiates a new wrapper.
     *
     * @param code the packageCode
     */
    public Result(int code) {
        this(code, "", null);
    }

    /**
     * Instantiates a new wrapper.
     *
     * @param code the code
     * @param msg  the msg
     * @param data the data
     */
    public Result(int code, String msg, T data) {
        super();
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    public Result(int code, String msg) {
        this.setCode(code);
        this.msg = msg;
    }

    public static <T> Result<T> failed() {
        return new Result<>(DEFAULT_ERROR);
    }

    public static Result failed(String msg) {
        return new Result<>(DEFAULT_ERROR, msg);
    }

    /**
     * Sets the 编号 , 返回自身的引用.
     *
     * @param code the new 编号
     */
    public Result code(int code) {
        this.setCode(code);
        return this;
    }

    /**
     * Sets the 信息 , 返回自身的引用.
     *
     * @param msg the new 信息
     * @return the wrapper
     */
    public Result<T> msg(String msg) {
        setMsg(msg);
        return this;
    }

    /**
     * Sets the 结果数据 , 返回自身的引用.
     *
     * @param data the new 结果数据
     * @return the wrapper
     */
    public Result<T> data(T data) {
        setData(data);
        return this;
    }

    public Result<T> extra(Map<Object, Object> extra) {
        setExtra(extra);
        return this;
    }

    public static <T> Result<T> result(int code, String msg, T data) {
        Result<T> instance = new Result<T>(code);
        instance.setMsg(msg);
        instance.setData(data);
        return instance;
    }

    public static <T> Result<T> ok() {
        return new Result<>(SUCCESS_CODE);
    }

    public static <T> Result<T> ok(T data) {
        Result<T> instance = new Result<T>();
        instance.setMsg("操作成功");
        instance.setData(data);
        return instance;
    }

    public static <T> Result<T> ok(int count, T data) {
        Result<T> instance = new Result<T>();
        instance.setData(data);
        instance.setCount(count);
        return instance;
    }

    public static <T> Result<T> ok(String msg, T data) {
        Result<T> instance = new Result<T>();
        instance.setData(data);
        instance.setMsg(msg);
        return instance;
    }

    /**
     * 判断是否成功： 依据 Result.SUCCESS_CODE == this.packageCode
     *
     * @return packageCode =0,true;否则 false.
     */
    @JsonIgnore
    public boolean success() {
        return Result.SUCCESS_CODE == this.code;
    }

    /**
     * 判断是否成功： 依据 Result.SUCCESS_CODE != this.packageCode
     *
     * @return packageCode !=200,true;否则 false.
     */
    @JsonIgnore
    public boolean error() {
        return !success();
    }

}
